﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Mozlite.Components;

namespace Mozlite.WebUI.Mvc4.Controllers
{
    /// <summary>
    /// 文件存储控制器。
    /// </summary>
    public class FileStorageController : BaseController
    {
        #region settings
        private FileStorageSettings fSettings;
        /// <summary>
        /// 获取当前文件存储配置。
        /// </summary>
        protected FileStorageSettings FSettings
        {
            get
            {
                if (fSettings == null)
                    fSettings = FileStorageSettings.Current;
                return fSettings;
            }
        }
        #endregion

        #region upload
        /// <summary>
        /// 上传文件。
        /// </summary>
        /// <param name="form">表单集合。</param>
        /// <returns>返回上传结果。</returns>
        [HttpPost]
        [AuthorizeEx]
        public ActionResult Upload(FormCollection form)
        {
            //最大文件大小
            long maxSize = FSettings.FileSize;
            var files = Request.Files;
            if (files.Count == 0)
                return JsonUploadError("FileStorages_SelectFileFirst");
            var folderID = form.Get<int>("fid");
            var file = new UserFile(files[0], folderID);

            String dirName = form.Get("dir");
            string allows;
            if (!FSettings.IsAllowed(file.Extension, dirName, out allows))
            {
                return JsonUploadError("FileStorages_FileTypeNotAllowwed", allows);
            }
            if (FileStorages.IsFolderNameExisted(Self.UserID, 0, file.FileName, folderID))
            {
                return JsonUploadError("FileStorages_DuplicateFolderName");
            }
            if (FileStorages.IsFileNameExisted(Self.UserID, folderID, file.FileName))
            {
                return JsonUploadError("FileStorages_DuplicateFileName");
            }
            if (file.File.InputStream == null || file.File.InputStream.Length > maxSize)
            {
                return JsonUploadError("FileStorages_OutFileLength");
            }
            if (file.Save())
                return Json(new { error = 0, url = file.Url });
            return JsonUploadError("FileStorages_UploadFailure");
        }

        private ActionResult JsonUploadError(object key, params object[] args)
        {
            return Json(new { error = 1, message = Local(key, args) });
        }
        #endregion

        #region browser
        /// <summary>
        /// 浏览文件。
        /// </summary>
        /// <returns>返回试图。</returns>
        public ActionResult Browser() {
            var folderID = Request["path"].To<int>();
            UserFolder folder;
            FileStorages.GetUserFolders(Self.UserID).TryGetValue(folderID, out folder);
            if (!folder.HasChildren && folder.Files.Count == 0)
            {
                ShowError("FileStorages_FileNotFound", folder);
            }

            String dirName = Request["dir"];
            if (!String.IsNullOrEmpty(dirName))
            {
                if (Array.IndexOf("image,flash,media,file".Split(','), dirName) == -1)
                {
                    ShowError("FileStorages_FileTypeError", folder);
                }
            }

            //图片扩展名
            String fileTypes = "gif,jpg,jpeg,png,bmp";

            //排序形式，name or size or type
            String order = Request["order"];
            order = String.IsNullOrEmpty(order) ? "" : order.ToLower();

            //遍历目录取得文件信息
            UserFolder[] dirList;
            if (folder.HasChildren)
                dirList = folder.Children.ToArray();
            else
                dirList = new UserFolder[0];
            UserFile[] fileList = folder.Files.ToArray();

            switch (order)
            {
                case "size":
                    Array.Sort(dirList, new NameSorter());
                    Array.Sort(fileList, new SizeSorter());
                    break;
                case "type":
                    Array.Sort(dirList, new NameSorter());
                    Array.Sort(fileList, new TypeSorter());
                    break;
                case "name":
                default:
                    Array.Sort(dirList, new NameSorter());
                    Array.Sort(fileList, new NameSorter());
                    break;
            }

            Hashtable result = new Hashtable();
            result["moveup_dir_path"] = folder.ParentID;
            result["current_dir_path"] = folder.FolderID;
            result["current_url"] = Cores.GetUrl("download.aspx?classid=");
            result["total_count"] = dirList.Length + fileList.Length;
            List<Hashtable> dirFileList = new List<Hashtable>();
            result["file_list"] = dirFileList;
            for (int i = 0; i < dirList.Length; i++)
            {
                var dir = dirList[i];
                Hashtable hash = new Hashtable();
                hash["id"] = dir.FolderID;
                hash["pid"] = dir.ParentID;
                hash["is_dir"] = true;
                hash["has_file"] = true;
                hash["filesize"] = 0;
                hash["is_photo"] = false;
                hash["filetype"] = "";
                hash["filename"] = dir.FolderName;
                hash["datetime"] = dir.LastUpdateDate.ToString("yyyy-MM-dd HH:mm:ss");
                dirFileList.Add(hash);
            }
            for (int i = 0; i < fileList.Length; i++)
            {
                var file = fileList[i];
                if (!FileStorageSettings.Current.IsType(file.Extension, dirName))
                    continue;
                Hashtable hash = new Hashtable();
                hash["id"] = file.FileID;
                hash["pid"] = file.FolderID;
                hash["is_dir"] = false;
                hash["has_file"] = false;
                hash["filesize"] = file.ContentLength;
                hash["is_photo"] = (Array.IndexOf(fileTypes.Split(','), file.Extension.Substring(1).ToLower()) >= 0);
                hash["filetype"] = file.Extension.Substring(1);
                hash["filename"] = file.FileName;
                hash["datetime"] = file.LastUpdateDate.ToString("yyyy-MM-dd HH:mm:ss");
                dirFileList.Add(hash);
            }
            return Json(result);
        }

        private ActionResult BrowserUploadError(string key, UserFolder folder)
        {
            Hashtable result = new Hashtable();
            result["moveup_dir_path"] = folder.ParentID;
            result["current_dir_path"] = folder.FolderID;
            result["current_url"] = Cores.GetUrl("download.aspx?classid=");
            result["total_count"] = 0;
            result["error"] = 1;
            result["message"] = Local(key);
            result["file_list"] = new List<Hashtable>();
            return Json(result);
        }

        public class NameSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                if (x.GetType() == typeof(UserFolder))
                    return ((UserFolder)x).FolderName.CompareTo(((UserFolder)y).FolderName);
                return ((UserFile)x).FileName.CompareTo(((UserFile)y).FileName);
            }
        }

        public class SizeSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                if (x.GetType() == typeof(UserFolder))
                    return ((UserFolder)x).ContentLength.CompareTo(((UserFolder)y).ContentLength);
                return ((UserFile)x).ContentLength.CompareTo(((UserFile)y).ContentLength);
            }
        }

        public class TypeSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                return ((UserFile)x).Extension.CompareTo(((UserFile)y).Extension);
            }
        }
        #endregion

        #region download
        /// <summary>
        /// 下载文件。
        /// </summary>
        /// <returns></returns>
        public ActionResult Download() {
            Guid attachmentID = Request.Get<Guid>("classid");
            if (attachmentID == Guid.Empty)
            {
                Response.StatusCode = 404;
                Response.End();
            }
            var file = FileStorages.GetStorageFile(attachmentID);
            if (file == null || !file.IsExists())
            {
                Response.StatusCode = 404;
                Response.End();
            }
            return File(file.Path, file.ContentType, Request.Get<string>("name", null));
            //Response.ContentType = file.ContentType;
            //Response.AddHeader("Content-Disposition", file.ContentDisposition);
            //Response.TransmitFile(file.Path);
        }
        #endregion
    }
}
